using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
using UnityStandardAssets.Utility;

namespace UnityStandardAssets.Characters.FirstPerson
{
	[RequireComponent(typeof(CharacterController))]
	[RequireComponent(typeof(AudioSource))]
	public class FirstPersonController : MonoBehaviour
	{
		[SerializeField]
		private bool m_IsWalking;

		[SerializeField]
		private float m_WalkSpeed;

		[SerializeField]
		private float m_RunSpeed;

		[SerializeField]
		[Range(0f, 1f)]
		private float m_RunstepLenghten;

		[SerializeField]
		private float m_JumpSpeed;

		[SerializeField]
		private float m_FlySpeed;

		[SerializeField]
		private float m_MaxJumpTime;

		[SerializeField]
		private float m_StickToGroundForce;

		[SerializeField]
		private float m_GravityMultiplier;

		[SerializeField]
		private MouseLook m_MouseLook;

		[SerializeField]
		private bool m_UseFovKick;

		[SerializeField]
		private FOVKick m_FovKick = new FOVKick();

		[SerializeField]
		private bool m_UseHeadBob;

		[SerializeField]
		private CurveControlledBob m_HeadBob = new CurveControlledBob();

		[SerializeField]
		private LerpControlledBob m_JumpBob = new LerpControlledBob();

		[SerializeField]
		private float m_StepInterval;

		[SerializeField]
		private AudioClip[] m_FootstepSounds;

		[SerializeField]
		private AudioClip m_JumpSound;

		[SerializeField]
		private AudioClip m_LandSound;

		[SerializeField]
		private AnimationClip _toolBobbingAnimationClip;

		[SerializeField]
		private Animation _toolBobbing;

		[SerializeField]
		private Camera m_Camera;

		private bool m_Jump;

		private bool m_JumpPressed;

		private bool m_JumpPressedExpired;

		private float m_startJumpTime;

		private float m_YRotation;

		private Vector2 m_Input;

		private Vector3 m_MoveDir = Vector3.zero;

		private CharacterController m_CharacterController;

		private CollisionFlags m_CollisionFlags;

		private bool m_PreviouslyGrounded;

		private Vector3 m_OriginalCameraPosition;

		private float m_StepCycle;

		private float m_NextStep;

		private bool m_Jumping;

		private AudioSource m_AudioSource;

		private const string m_JumpKey = "Jump";

		private const string m_FlyUpKey = "FlyUp";

		private const string m_FlyDownKey = "FlyDown";

		private const string m_FlyEnableKey = "FlyEnable";

		private const string m_JumpEnableKey = "JumpEnable";

		private bool m_Flying;

		private bool m_InitialJumpThrust;

		private float m_DefaultGravityMultiplier;

		private void Start()
		{
			m_CharacterController = GetComponent<CharacterController>();
			m_CharacterController.enableOverlapRecovery = true;
			m_OriginalCameraPosition = m_Camera.transform.localPosition;
			m_FovKick.Setup(m_Camera);
			m_HeadBob.Setup(m_Camera, m_StepInterval);
			m_StepCycle = 0f;
			m_NextStep = m_StepCycle / 2f;
			m_Jumping = false;
			m_JumpPressed = false;
			m_JumpPressedExpired = false;
			m_AudioSource = GetComponent<AudioSource>();
			m_MouseLook.Init(base.transform, m_Camera.transform);
			m_DefaultGravityMultiplier = m_GravityMultiplier;
		}

		private void Update()
		{
			RotateView();
			UdateToogleFlyJump();
			UpdateJump();
			UpdateFly();
		}

		private void UdateToogleFlyJump()
		{
			if (CrossPlatformInputManager.GetButtonUp("JumpEnable"))
			{
				m_Flying = false;
				m_Jump = false;
				m_InitialJumpThrust = false;
				m_GravityMultiplier = m_DefaultGravityMultiplier;
			}
			if (CrossPlatformInputManager.GetButtonUp("FlyEnable"))
			{
				m_Flying = true;
				m_Jump = false;
				m_InitialJumpThrust = true;
				m_GravityMultiplier = 0f;
				m_FlySpeed = 5f;
			}
		}

		private void UpdateFly()
		{
			if (!m_Flying)
			{
				return;
			}
			if (m_InitialJumpThrust)
			{
				m_FlySpeed -= 5f * Time.deltaTime;
				if (m_FlySpeed <= 0f)
				{
					m_FlySpeed = 0f;
					m_InitialJumpThrust = false;
				}
			}
			if (CrossPlatformInputManager.GetButtonDown("FlyUp"))
			{
				m_InitialJumpThrust = false;
				m_FlySpeed = 5f;
			}
			if (CrossPlatformInputManager.GetButtonUp("FlyUp"))
			{
				m_InitialJumpThrust = false;
				m_FlySpeed = 0f;
			}
			if (CrossPlatformInputManager.GetButtonDown("FlyDown"))
			{
				m_InitialJumpThrust = false;
				m_FlySpeed = -5f;
			}
			if (CrossPlatformInputManager.GetButtonUp("FlyDown"))
			{
				m_InitialJumpThrust = false;
				m_FlySpeed = 0f;
			}
		}

		private void UpdateJump()
		{
			if (!m_Flying)
			{
				if (!m_Jump)
				{
					m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
				}
				if (CrossPlatformInputManager.GetButtonDown("Jump"))
				{
					m_JumpPressed = true;
					m_startJumpTime = Time.time;
				}
				if (CrossPlatformInputManager.GetButtonUp("Jump"))
				{
					m_JumpPressed = false;
				}
				if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
				{
					StartCoroutine(m_JumpBob.DoBobCycle());
					PlayLandingSound();
					m_MoveDir.y = 0f;
					m_Jumping = false;
				}
				if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
				{
					m_MoveDir.y = 0f;
				}
				m_PreviouslyGrounded = m_CharacterController.isGrounded;
			}
		}

		private void PlayLandingSound()
		{
			m_AudioSource.clip = m_LandSound;
			m_AudioSource.Play();
			m_NextStep = m_StepCycle + 0.5f;
		}

		private void FixedUpdate()
		{
			GetInput(out float speed);
			Vector3 vector = base.transform.forward * m_Input.y + base.transform.right * m_Input.x;
			Physics.SphereCast(base.transform.position, m_CharacterController.radius, Vector3.down, out RaycastHit hitInfo, m_CharacterController.height / 2f, -1, QueryTriggerInteraction.Ignore);
			vector = Vector3.ProjectOnPlane(vector, hitInfo.normal).normalized;
			m_MoveDir.x = vector.x * speed;
			m_MoveDir.z = vector.z * speed;
			if (m_CharacterController.isGrounded)
			{
				m_MoveDir.y = 0f - m_StickToGroundForce;
				m_JumpPressedExpired = false;
				if (m_Jump)
				{
					m_MoveDir.y = m_JumpSpeed;
					PlayJumpSound();
					m_Jump = false;
					m_Jumping = true;
				}
				if (m_Flying)
				{
					m_MoveDir.y = m_FlySpeed;
				}
			}
			else
			{
				if (!m_JumpPressedExpired && m_JumpPressed && Time.time - m_startJumpTime <= m_MaxJumpTime)
				{
					m_MoveDir.y = m_JumpSpeed;
					m_Jump = false;
					m_Jumping = true;
				}
				else
				{
					m_JumpPressedExpired = true;
					m_MoveDir += Physics.gravity * m_GravityMultiplier * Time.fixedDeltaTime;
				}
				if (m_Flying)
				{
					m_MoveDir.y = m_FlySpeed;
				}
			}
			m_CollisionFlags = m_CharacterController.Move(m_MoveDir * Time.fixedDeltaTime);
			ProgressStepCycle(speed);
			UpdateCameraPosition(speed);
		}

		private void PlayJumpSound()
		{
			m_AudioSource.clip = m_JumpSound;
			m_AudioSource.Play();
		}

		private void ProgressStepCycle(float speed)
		{
			if (m_CharacterController.velocity.sqrMagnitude > 0f && (m_Input.x != 0f || m_Input.y != 0f))
			{
				m_StepCycle += (m_CharacterController.velocity.magnitude + speed * ((!m_IsWalking) ? m_RunstepLenghten : 1f)) * Time.fixedDeltaTime;
			}
			if (m_StepCycle > m_NextStep)
			{
				m_NextStep = m_StepCycle + m_StepInterval;
				PlayFootStepAudio();
			}
		}

		private void PlayFootStepAudio()
		{
			if (m_CharacterController.isGrounded)
			{
				int num = UnityEngine.Random.Range(1, m_FootstepSounds.Length);
				m_AudioSource.clip = m_FootstepSounds[num];
				m_AudioSource.PlayOneShot(m_AudioSource.clip);
				m_FootstepSounds[num] = m_FootstepSounds[0];
				m_FootstepSounds[0] = m_AudioSource.clip;
			}
		}

		private void UpdateCameraPosition(float speed)
		{
			if (!m_UseHeadBob)
			{
				return;
			}
			Vector3 localPosition;
			if (m_CharacterController.velocity.magnitude > 0f && m_CharacterController.isGrounded)
			{
				m_Camera.transform.localPosition = m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude + speed * ((!m_IsWalking) ? m_RunstepLenghten : 1f));
				localPosition = m_Camera.transform.localPosition;
				Vector3 localPosition2 = m_Camera.transform.localPosition;
				localPosition.y = localPosition2.y - m_JumpBob.Offset();
				_toolBobbing[_toolBobbingAnimationClip.name].speed = 1f;
				if (!_toolBobbing.isPlaying)
				{
					_toolBobbing.Play();
				}
			}
			else
			{
				_toolBobbing[_toolBobbingAnimationClip.name].speed = 0f;
				localPosition = m_Camera.transform.localPosition;
				localPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
			}
			m_Camera.transform.localPosition = localPosition;
		}

		private void GetInput(out float speed)
		{
			float axis = CrossPlatformInputManager.GetAxis("Horizontal");
			float axis2 = CrossPlatformInputManager.GetAxis("Vertical");
			bool isWalking = m_IsWalking;
			speed = Mathf.Sqrt(axis * axis + axis2 * axis2) * ((!m_Flying) ? m_WalkSpeed : (m_WalkSpeed * 2f));
			if (UnityEngine.Input.GetKey(KeyCode.LeftShift))
			{
				speed *= 3f;
			}
			m_Input = new Vector2(axis, axis2);
			if (m_Input.sqrMagnitude > 1f)
			{
				m_Input.Normalize();
			}
			if (m_IsWalking != isWalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0f)
			{
				StopAllCoroutines();
				StartCoroutine(m_IsWalking ? m_FovKick.FOVKickDown() : m_FovKick.FOVKickUp());
			}
		}

		private void RotateView()
		{
			m_MouseLook.LookRotation(base.transform, m_Camera.transform);
		}

		private void OnControllerColliderHit(ControllerColliderHit hit)
		{
			Rigidbody attachedRigidbody = hit.collider.attachedRigidbody;
			if (m_CollisionFlags != CollisionFlags.Below && !(attachedRigidbody == null) && !attachedRigidbody.isKinematic)
			{
				attachedRigidbody.AddForceAtPosition(m_CharacterController.velocity * 0.1f, hit.point, ForceMode.Impulse);
			}
		}

		public void ForceOrientation(Vector3 orientation)
		{
			m_MouseLook.ForceOrientation(orientation);
		}
	}
}
